#include <rtthread.h>
#include <rtdevice.h>
#include "touch.h"
#include "driver_touch.h"
#include "nuc970_gpio.h"
#include "message.h"

#define TOUCH_POINT_NUMB    1

typedef struct _touch_state
{
    rt_uint8_t  touchDetected;                      /*!< Total number of active touches detected at last scan */
    rt_uint8_t  event;                              /* The touch event of the data */
#if (TOUCH_POINT_NUMB == 1)
    rt_uint16_t touchX;                             /*!< Touch X coordinates on 12 bits */
    rt_uint16_t touchY;                             /*!< Touch Y coordinates on 12 bits */
#else
    rt_uint16_t touchX[TOUCH_POINT_NUMB];           /*!< Touch X coordinates on 12 bits */
    rt_uint16_t touchY[TOUCH_POINT_NUMB];           /*!< Touch Y coordinates on 12 bits */
#endif
}TouchState;

static rt_thread_t  touch_thread = RT_NULL;
static rt_sem_t     touch_sem = RT_NULL;
static rt_device_t  dev = RT_NULL;
static struct rt_touch_data *touch_data;
int g_isMirrorX, g_isMirrorY;
int g_xSize, g_ySize;

void nu_touch_inputevent_cb(rt_int16_t x, rt_int16_t y, rt_uint8_t state);

static void getTouchState(TouchState *touchState)
{
    rt_uint8_t i = 0;

    touchState->touchDetected = rt_device_read(dev, 0, touch_data, TOUCH_POINT_NUMB);
    if (touchState->touchDetected > 0 && touchState->touchDetected <= TOUCH_POINT_NUMB) {
        for (i = 0; i < touchState->touchDetected; i++) {
            if (touch_data[i].event == RT_TOUCH_EVENT_DOWN || touch_data[i].event == RT_TOUCH_EVENT_MOVE) {
#if (TOUCH_POINT_NUMB == 1)
                touchState->touchX = touch_data[i].y_coordinate;
                touchState->touchY = g_ySize - touch_data[i].x_coordinate-1;

                if (touchState->touchX > g_xSize-1) {
                    touchState->touchX = g_xSize-1;
                }
                if (touchState->touchY > g_ySize-1) {
                    touchState->touchY = g_ySize-1;
                }
#else
                touchState->touchX[i] = touch_data[i].y_coordinate;
                touchState->touchY[i] = g_ySize - touch_data[i].x_coordinate-1;

                if (touchState->touchX[i] > g_xSize-1) {
                    touchState->touchX[i] = g_xSize-1;
                }
                if (touchState->touchY[i] > g_ySize-1) {
                    touchState->touchY[i] = g_ySize-1;
                }
#endif
            }
            switch (touch_data[i].event){
            case RT_TOUCH_EVENT_UP:
                touchState->event = RT_TOUCH_EVENT_UP;
            break;
            case RT_TOUCH_EVENT_DOWN:
                touchState->event = RT_TOUCH_EVENT_DOWN;
            break;
            case RT_TOUCH_EVENT_MOVE:
                touchState->event = RT_TOUCH_EVENT_MOVE;
            break;
            default:
                touchState->event = RT_TOUCH_EVENT_NONE;
            break;
            }
        }
    }
}

static rt_err_t rx_callback(rt_device_t dev, rt_size_t size)
{
    GPIO_ClrISRBit(GPIOG, BIT13);

    rt_sem_release(touch_sem);
    return 0;
}

static void touch_thread_entry(void *parameter)
{
    rt_uint16_t /*x, y, */trig_type;
    rt_uint8_t task_prio = 0;

    rt_hw_iic_touch();

    dev = rt_device_find("touch");
    if (dev == RT_NULL) {
        rt_kprintf("can't find device:%s\n", "touch");
        return;
    }
    if (rt_device_open(dev, RT_DEVICE_FLAG_INT_RX) != RT_EOK) {
        rt_kprintf("open device failed!");
        return;
    }

    touch_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_PRIO);
    if (touch_sem == RT_NULL) {
        rt_kprintf("create dynamic semaphore failed.\n");
        return;
    }

    rt_device_set_rx_indicate(dev, rx_callback);

    trig_type = RT_DEVICE_FLAG_INT_RX;
    rt_device_control(dev, RT_TOUCH_CTRL_SET_MODE, &trig_type);
//    rt_device_control(dev, RT_TOUCH_CTRL_SET_X_RANGE, &x);  /* if possible you can set your x y coordinate*/
//    rt_device_control(dev, RT_TOUCH_CTRL_SET_Y_RANGE, &y);

    touch_data = (struct rt_touch_data *)rt_malloc(sizeof(struct rt_touch_data) * TOUCH_POINT_NUMB);

    g_xSize = LCD_GetXSize();
    g_ySize = LCD_GetYSize();

    rt_thread_control(touch_thread, RT_THREAD_CTRL_CHANGE_PRIORITY, (void *)&task_prio);
    while (1) {
        rt_sem_take(touch_sem, RT_WAITING_FOREVER);
//        rt_device_control(dev, RT_TOUCH_CTRL_DISABLE_INT, RT_NULL);
        GUI_PID_X_Exec();
        rt_thread_mdelay(10);
//        rt_device_control(dev, RT_TOUCH_CTRL_ENABLE_INT, RT_NULL);
    }
}

static int touch_thread_init(void)
{
    touch_thread = rt_thread_create("touch", touch_thread_entry, RT_NULL,
                                     2048,
                                     RT_MAIN_THREAD_PRIORITY+1,
                                     2);
    if (touch_thread != RT_NULL)
        rt_thread_startup(touch_thread);

    return 0;
}
INIT_APP_EXPORT(touch_thread_init);
